package com.im.server.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 描述：日期工具类
 * <p>
 * 作者：HuTongFu
 * 时间：2019/7/12 15:30
 */
public class DateUtil {

    private static final Logger logger = LoggerFactory.getLogger(DateUtil.class);
    private static final String DATE_PATTERN = "yyyy-MM-dd";
    private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * 应用程序的格式化符
     */
    public static final String DATE_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
    /**
     * 短日期格式
     */
    public static final String DATE_FORMAT_YMD = "yyyy-MM-dd";

    /**
     * 日期转字符串
     *
     * @param date 日期
     * @return String 转换之后的日期字符串
     */
    public static String dateConvertToString(Date date) {
        return dateConvertToString(date, DATE_TIME_PATTERN);
    }

    /**
     * 日期转字符串
     *
     * @param date   日期
     * @param format @{see DATE_TIME_PATTERN }
     * @return String 转换之后的日期字符串
     */
    public static String dateConvertToString(Date date, String format) {
        SimpleDateFormat fmt = new SimpleDateFormat(format);
        date = date == null ? new Date() : date;
        return fmt.format(date);
    }

    /**
     * 字符串转日期
     *
     * @param dateStr 日期字符串
     * @return Date 转换之后的日期
     */
    public static Date stringConvertToDate(String dateStr) {
        return stringConvertToDate(dateStr, DATE_PATTERN);
    }

    /**
     * 字符串转日期
     *
     * @param dateStr   日期字符串
     * @param formatter 格式
     * @return Date 转换之后的日期
     */
    public static Date stringConvertToDate(String dateStr, String formatter) {
        SimpleDateFormat fmt = new SimpleDateFormat(formatter);
        Date result = null;
        try {
            if (StringUtils.isNotEmpty(dateStr)) {
                result = fmt.parse(dateStr);
            }
        } catch (ParseException e) {
            logger.error("convert the Date({}) occur errors:{}", dateStr, e.getMessage());
        }
        return result;
    }

    /**
     * 计算距离现在多久，非精确
     *
     * @param date
     * @return
     */
    public static String getTimeBefore(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        } else if (hour > 0) {
            r += hour + "小时";
        } else if (min > 0) {
            r += min + "分";
        } else if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }

    /**
     * 计算距离现在多久，精确
     *
     * @param date
     * @return
     */
    public static String getTimeBeforeAccurate(Date date) {
        Date now = new Date();
        long l = now.getTime() - date.getTime();
        long day = l / (24 * 60 * 60 * 1000);
        long hour = (l / (60 * 60 * 1000) - day * 24);
        long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60);
        long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        String r = "";
        if (day > 0) {
            r += day + "天";
        }
        if (hour > 0) {
            r += hour + "小时";
        }
        if (min > 0) {
            r += min + "分";
        }
        if (s > 0) {
            r += s + "秒";
        }
        r += "前";
        return r;
    }

    /**
     * 得到当前时间，例如"2002-11-06 17:08:59"
     *
     * @return String 日期字符串
     */
    public static String getCurrentTime() {
        SimpleDateFormat formatter = new SimpleDateFormat(DATE_TIME_PATTERN);
        Date date = new Date();
        return formatter.format(date);
    }


    /**
     * 设置当前时间为当天的最初时间（即00时00分00秒）
     *
     * @param cal
     * @return
     */
    public static Calendar setStartDay(Calendar cal) {
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        return cal;
    }

    public static Calendar setEndDay(Calendar cal) {
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal;
    }

    /**
     * 把源日历的年月日设置到目标日历对象中
     *
     * @param destCal
     * @param sourceCal
     */
    public static void copyYearMonthDay(Calendar destCal, Calendar sourceCal) {
        destCal.set(Calendar.YEAR, sourceCal.get(Calendar.YEAR));
        destCal.set(Calendar.MONTH, sourceCal.get(Calendar.MONTH));
        destCal.set(Calendar.DAY_OF_MONTH, sourceCal.get(Calendar.DAY_OF_MONTH));
    }

    /**
     * 格式化日期为
     *
     * @return
     */
    public static String formatEnDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a");
        return sdf.format(date).replaceAll("上午", "AM").replaceAll("下午", "PM");
    }

    /**
     * 解析日期字符串格式
     *
     * @param dateString
     * @return
     */
    public static Date parseDate(String dateString) {
        Date date = null;
        try {
            date = DateUtils.parseDate(dateString, new String[]{DATE_TIME_PATTERN, DATE_PATTERN});
        } catch (Exception ex) {
            logger.error("Pase the Date({}) occur errors:{}", dateString, ex.getMessage());
        }
        return date;
    }

    /**
     * 日期加一天
     *
     * @param date
     * @return
     */
    public static String addOneDay(String date) {
        DateFormat format = new SimpleDateFormat(DATE_PATTERN);
        Calendar calendar = Calendar.getInstance();
        try {
            Date dd = format.parse(date);
            calendar.setTime(dd);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        } catch (ParseException e) {
            logger.error("Pase the Date({}) occur errors:{}", date, e.getMessage());
        }
        String tmpDate = format.format(calendar.getTime());
        return tmpDate.substring(5, 7) + "/" + tmpDate.substring(8, 10) + "/" + tmpDate.substring(0, 4);
    }

    /**
     * 加一小时
     *
     * @param date
     * @return
     */
    public static String addOneHour(String date) {
        String amPm = date.substring(20, 22);
        DateFormat format = new SimpleDateFormat(DATE_TIME_PATTERN);
        Calendar calendar = Calendar.getInstance();

        int hour = Integer.parseInt(date.substring(11, 13));
        try {
            if (amPm.equals("PM")) {
                hour += 12;
            }
            date = date.substring(0, 11) + (hour >= 10 ? hour : "0" + hour) + date.substring(13, 19);
            Date dd = format.parse(date);
            calendar.setTime(dd);
            calendar.add(Calendar.HOUR_OF_DAY, 1);
        } catch (ParseException e) {
            logger.error("Pase the Date({}) occur errors:{}", date, e.getMessage());
        }
        String tmpDate = format.format(calendar.getTime());

        hour = Integer.parseInt(tmpDate.substring(11, 13));
        amPm = hour >= 12 && hour != 0 ? "PM" : "AM";
        if (amPm.equals("PM")) {
            hour -= 12;
        }
        tmpDate = tmpDate.substring(5, 7) + "/" + tmpDate.substring(8, 10) + "/" + tmpDate.substring(0, 4)
                + " " + (hour >= 10 ? hour : "0" + hour) + tmpDate.substring(13, tmpDate.length()) + " " + amPm;

        return tmpDate;
    }

    /**
     * 标准时间格式转为时间字符格式
     *
     * @param timeStr eg:Mon Feb 06 00:00:00 CST 2012
     * @return
     */
    public static String timeStrToDateStr(String timeStr) {

        String dateStr = timeStr.substring(24, 28) + "-";

        String mon = timeStr.substring(4, 7);
        if (mon.equals("Jan")) {
            dateStr += "01";
        } else if (mon.equals("Feb")) {
            dateStr += "02";
        } else if (mon.equals("Mar")) {
            dateStr += "03";
        } else if (mon.equals("Apr")) {
            dateStr += "04";
        } else if (mon.equals("May")) {
            dateStr += "05";
        } else if (mon.equals("Jun")) {
            dateStr += "06";
        } else if (mon.equals("Jul")) {
            dateStr += "07";
        } else if (mon.equals("Aug")) {
            dateStr += "08";
        } else if (mon.equals("Sep")) {
            dateStr += "09";
        } else if (mon.equals("Oct")) {
            dateStr += "10";
        } else if (mon.equals("Nov")) {
            dateStr += "11";
        } else if (mon.equals("Dec")) {
            dateStr += "12";
        }

        dateStr += "-" + timeStr.substring(8, 10);

        return dateStr;
    }


    /**
     * 根据日期得到星期多余天数
     *
     * @param sDate
     * @return
     */
    public static int getExtraDayOfWeek(String sDate) {
        try {

            String formater = "yyyy-MM-dd";
            SimpleDateFormat format = new SimpleDateFormat(formater);
            Date date = format.parse(sDate);
            String weekday = date.toString().substring(0, 3);
            if (weekday.equals("Mon")) {
                return 1;
            } else if (weekday.equals("Tue")) {
                return 2;
            } else if (weekday.equals("Wed")) {
                return 3;
            } else if (weekday.equals("Thu")) {
                return 4;
            } else if (weekday.equals("Fri")) {
                return 5;
            } else if (weekday.equals("Sat")) {
                return 6;
            } else {
                return 0;
            }

        } catch (Exception ex) {
            return 0;
        }
    }

    /**
     * 根据日期得到星期多余天数
     *
     * @param sDate
     * @return
     */
    public static String getDateWeekDay(String sDate) {
        try {

            String formater = "yyyy-MM-dd";
            SimpleDateFormat format = new SimpleDateFormat(formater);
            Date date = format.parse(sDate);
            String weekday = date.toString().substring(0, 3);
//			format.format(date)+" "+
            return weekday;

        } catch (Exception ex) {
            return "";
        }
    }

    /**
     * 取得上下五年
     *
     * @param cal
     * @return
     */
    public static List<String> getUpDownFiveYear(Calendar cal) {
        List<String> yearlist = new ArrayList<String>();

        int curyear = cal.get(Calendar.YEAR);
        yearlist.add(String.valueOf(curyear - 2));
        yearlist.add(String.valueOf(curyear - 1));
        yearlist.add(String.valueOf(curyear));
        yearlist.add(String.valueOf(curyear + 1));
        yearlist.add(String.valueOf(curyear + 2));

        return yearlist;
    }

    /**
     * 取得12个月
     */
    public static List<String> getTwelveMonth() {
        List<String> monthlist = new ArrayList<String>();

        for (int idx = 1; idx <= 12; idx++) {
            monthlist.add(String.valueOf(idx));
        }

        return monthlist;
    }

    /**
     * 得到两日期间所有日期
     *
     * @param startTime
     * @param endTime
     * @return
     * @throws Exception
     */
    public static String[] getDaysBetweenDate(String startTime, String endTime) {

        String[] dateArr = null;
        try {

            String stime = timeStrToDateStr(startTime);
            String etime = timeStrToDateStr(endTime);

            //日期相减算出秒的算法
            Date date1 = new SimpleDateFormat("yyyy-MM-dd").parse(stime);
            Date date2 = new SimpleDateFormat("yyyy-MM-dd").parse(etime);

            long day = (date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000) > 0 ? (date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000) :
                    (date2.getTime() - date1.getTime()) / (24 * 60 * 60 * 1000);

            dateArr = new String[Integer.valueOf(String.valueOf(day + 1))];
            for (int idx = 0; idx < dateArr.length; idx++) {
                if (idx == 0) {
                    dateArr[idx] = stime;
                } else {
                    stime = addOneDay(stime);
                    stime = stime.substring(6, 10) + "-" + stime.substring(0, 2)
                            + "-" + stime.substring(3, 5);
                    dateArr[idx] = stime;
                }
            }

        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return dateArr;
    }


    /**
     * 得到几天后的时间
     */
    public static Date getDateAfter(Date d, int day) {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.set(Calendar.DATE, now.get(Calendar.DATE) + day);
        return now.getTime();
    }

    /**
     * 得到几天前的时间
     */
    public static Date getDateBefore(Date d, int day) {
        Calendar now = Calendar.getInstance();
        now.setTime(d);
        now.set(Calendar.DATE, now.get(Calendar.DATE) - day);
        return now.getTime();
    }


    /**
     * 判断两个日期 是否是同一天
     */

    public static boolean isSameDate(Date date1, Date date2) {

        //从无到有。判断为改变
        if (null == date1 && null != date2) {
            return false;
        }
        if (null == date2 && null != date1) {
            return false;
        }
        if (null == date1 && null == date2) {
            return true;
        }
        //判断开始
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);

        boolean isSameYear = cal1.get(Calendar.YEAR) == cal2
                .get(Calendar.YEAR);
        boolean isSameMonth = isSameYear
                && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
        boolean isSameDate = isSameMonth
                && cal1.get(Calendar.DAY_OF_MONTH) == cal2
                .get(Calendar.DAY_OF_MONTH);

        return isSameDate;
    }
}
